import type * as fsType from "fs";
import type * as fpath from 'path';
import type * as os from "os";

@IEditorEnv.regClass()
export class TreeSave {

    static async treeSave(this:IEditorEnv.IGameScene,nodeid:string,name:string){
        let node = this.getNodeById(nodeid);
        let components = node.components;
        let com: Laya.Component = null;
        for (let i = components.length - 1; i >= 0; i--) {
            if (components[i].scriptPath && 0 <= components[i].scriptPath.indexOf("ProgrammedTreeRender")) {
                com = components[i];
                break;
            }
        }
        if (com) {
            if ("saveMaterial" == name) {
                let ms = (com as any).sharedMaterials;
                delete ms[0].paramTexture.uuid;
                delete ms[0].albedoTexture.uuid;
                //modifyMaterial(com, ms, 'treeExport/Material/TreeMaterial.lmat');
                let srcT = await TreeSave.modifyMaterial(com, ms, ["treeExport", "Material"]);
                if (srcT) {
                    let lmatPath = 'treeExport/Material/TreeMaterial.lmat';
                    
                    await IEditorEnv.createMaterial(ms[0], lmatPath);
                    (ms[0] as any).paramTexture = srcT;
                    TreeSave.modifyMaterialType(lmatPath);
                }

            }
            else if ('saveProfab' == name) {
                var sp = new Laya.Sprite3D();
                var filter = sp.addComponent(Laya.MeshFilter)
                filter.sharedMesh = (com as any).getMesh().clone();
                var render = sp.addComponent(Laya.MeshRenderer)
                render.sharedMaterial = (com as any).sharedMaterial;
                let ms = (com as any).sharedMaterials;
                let dirPath = ["treeExport", "Profab"];
                console.log((ms[0].albedoTexture as Laya.Texture2D)._gammaSpace);
                delete ms[0].paramTexture.uuid;
                delete ms[0].albedoTexture.uuid;
                let srcT = await TreeSave.modifyMaterial(com, ms, dirPath);
                // render.sharedMaterial = new BlinnPhongMaterial();
                await IEditorEnv.createPrefab(sp, 'treeExport/Profab/TreePrefab.lh');
                if (srcT) {
                    (ms[0] as any).paramTexture = srcT;

                    let lmatPath = fpath.join(...dirPath, 'TreePrefab_0.lmat');
                    TreeSave.modifyMaterialType(lmatPath);
                }
            }
            else if ('saveMesh' == name) {

                let mh = (com as any).getMesh();
                console.log(mh);
                IEditorEnv.createMesh(mh, "treeExport/Mesh/TreeMesh.lm");
            }
            else if('treeRadiusFit' == name)
            {
                let edit = (com as any).treeEdit;
                edit.tr.cfg.branchRadiusFit();
                edit.updateTree();
            }
            else {

            }
        }
    }

    static modifyMaterialType(lmatPath: string, type = 'TreeCore') {
        const fs: typeof fsType = require("fs");
        let jsonAbsPath = fpath.join(EditorEnv.assetsPath, lmatPath);
        
        let json = JSON.parse(fs.readFileSync(jsonAbsPath,'utf-8'));
        if (json) {
            try {
                json.props.type = type;
                fs.writeFileSync(jsonAbsPath, JSON.stringify(json));
            } catch (err) { }
        }
    }
    
    static async modifyMaterial(com: any, ms: Laya.Material[], paths: string[]) {
        const fs: typeof fsType = require("fs");
        if (ms && 0 < ms.length) {
            let mat = ms[0];
            let pixData = (com as any).treeEdit.tr.tpd16;
            let wh = Math.sqrt(pixData.length / 4);
            let ktxDir = fpath.join(...paths);
            let ktxAbsDir = fpath.join(EditorEnv.assetsPath, ktxDir);
            if (!fs.existsSync(ktxAbsDir)) {
                fs.mkdirSync(ktxAbsDir, { recursive: true });
            }
            let ktxAbsPath = fpath.join(ktxAbsDir, "TreeMaterial.ktx");
            await this.textureToKTX(pixData, wh, wh, ktxAbsPath, "RGBA16");
            
            let ktxPath = fpath.join(ktxDir, 'TreeMaterial.ktx');
            let ktxInfo = EditorEnv.assetMgr.getAsset(ktxPath);
            if (null == ktxInfo) {
                ktxInfo = EditorEnv.assetMgr.createFileAsset(ktxPath);
            }
            EditorEnv.assetMgr.setMetaData(ktxInfo, { importer: { "sRGB": false, "filterMode": 0, "generateMipmap": false, 'anisoLevel': 1 } });
    
            let srcT = (mat as any).paramTexture as Laya.Texture2D;
            let t = (mat as any).paramTexture as Laya.Texture2D;
            t.uuid = ktxInfo.id;
    
            return srcT;
    
            // await CreateAssetUtil.createMaterial(mat, lmatPath);
            // (mat as any).paramTexture = srcT;
    
        }
        return null;
    }

    static async textureToKTX(buffer: ArrayBufferView, w: number, h: number, outputPath: string, textureFormat = "RGBA32") {
        const fs: typeof fsType = require("fs");
        var tmpPath = os.tmpdir();
        let filePath = fpath.join(tmpPath, `tmpCube.bin`);
        fs.writeFileSync(filePath, buffer as any);
        var args: string[] = [];

        args.push("-w", w.toString(), "-h", h.toString(), "-f", textureFormat, "-i", filePath, "-o", outputPath);
        let ret = await IEditorEnv.runTool("KtxPixelTool", args);
        if (ret.code != 0) {
            console.error(`KtxPixelTool failed with '${ret.output}'`);
            return false
        }
        return true
    }
}
